#include "StdAfx.h"
#include "DVBRule.h"

#define MAX_LINE_SIZE		128
#define ELEMENT_TAG			1
#define ELEMENT_VALUE		2
#define ELEMENT_DEPTH		16
#define ELEMENT_MAX_LENGTH	32

#define ELEMENT_START		0x01
#define ELEMENT_END			0x02
#define ELEMENT_ATTRIBUTE	0x04


typedef struct _search_result
{
	element_node *pNode;
	_search_result *pNext;
}search_result;

static char skipped[] = {0x9, 0x0A, 0x0D, 0x20};
static char element[32] = {0};
static char value[32] = {0};
static char status = 0;
static char* pWrite = NULL;

static element_node* element_stack[ELEMENT_DEPTH+1] = {0};
static element_node **stack_top = element_stack;
static element_node **stack_bottom = element_stack;

static element_node *pRoot_node = NULL;
static search_result *pTableHead = NULL;
static search_result *pDescriptorHead = NULL;
static search_result *pTempHead = NULL;

static BOOL GetLine(CFile* hFile, ULONGLONG &nPos, char* szLine, int nMaxSize);
static BOOL ParseLine(char* szLine);
static BOOL IsSkipped(const char c);
static void readchar(const char ch);

static BOOL createroot(element_node* pNode);
static BOOL addChild(element_node* pNode, element_node *pParent);
static BOOL freeDVBTree(element_node* pTreeRoot);
static void getElementByTagName(char *pName, element_node *pTree);
static void findElementByTagName(char *pName, element_node *pTree);
static void findElementInChildByTagName(char *pName, element_node *pTree);
static element_node* getChildNode(int nIndex, element_node* pNode);
static BOOL addSearchResult(element_node* pNode);
static BOOL clearSearchResult(void);
static int getElementDepth(element_node* pElement);
static BOOL outputXMLTree(CFile* hFile, element_node* pTreeRoot);

static int getDescriptorCount(void);
static int getDescriptorIndex(BYTE bDescriptorTag);
static element_node* getDescriptor(int nIndex);
static char* getDescriptorName(int nIndex);

//utility function
static BYTE dvb_atob(char* pData);
static BYTE dvb_formatType(char* pType);

//
static void pushelement(element_node *pElement);
static element_node* popelement(void);
static element_node* gettopelement(void);

CDVBRule::CDVBRule(void)
{
	m_hRulesFile = NULL;
	m_nTableCount = 0;
	m_nDescriptorCount = 0;
	m_bFileUpdated = TRUE;
	m_hRulesFile = new CFile();
	
	TCHAR dir[64];
	GetCurrentDirectory(64, dir);
	CString path(dir);
	path += "\\rules.xml";

	CFileException e;
	CFileStatus fs;
	if(m_hRulesFile->GetStatus(path, fs))
	{
		if(m_hRulesFile->Open(path, CFile::modeReadWrite|CFile::shareDenyWrite, &e))
		{
		}
	}
	else
	{
		if(m_hRulesFile->Open(path, CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite,&e))
		{
			FormatDefaultFile();			
		}
	}

	FormatVerify();
}

CDVBRule::~CDVBRule(void)
{
	if(m_hRulesFile)
	{
		m_hRulesFile->Close();
		delete m_hRulesFile;
		m_hRulesFile = NULL;
	}
	if(pRoot_node)
	{
		freeDVBTree(pRoot_node);
	}

	clearSearchResult();
}

void CDVBRule::FormatDefaultFile(void)
{
	if(m_hRulesFile)
	{
		char szText[128];

		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "<DVB>\r\n");		
		m_hRulesFile->Write(szText, strlen(szText));

		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "\t<TABLEDEF>\r\n");
		m_hRulesFile->Write(szText, strlen(szText));


		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "\t</TABLEDEF>\r\n");
		m_hRulesFile->Write(szText, strlen(szText));


		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "\t<DESCRIPTORDEF>\r\n");
		m_hRulesFile->Write(szText, strlen(szText));

		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "\t</DESCRIPTORDEF>\r\n");
		m_hRulesFile->Write(szText, strlen(szText));

		memset(szText, '\0', sizeof(szText));
		sprintf_s(szText, 127, "</DVB>");
		m_hRulesFile->Write(szText, strlen(szText));
	}
}

BOOL CDVBRule::FormatVerify(void)
{
	BOOL bRet = FALSE;
	ULONGLONG nPos;
	
	if(pRoot_node)
	{
		freeDVBTree(pRoot_node);
		pRoot_node = NULL;
	}

	m_hRulesFile->Seek(0, CFile::begin);
	nPos = m_hRulesFile->GetPosition();

	char szLine[MAX_LINE_SIZE];
	memset(szLine, '\0', sizeof(szLine));
	int nLineCount = 0;
	while(GetLine(m_hRulesFile, nPos, szLine, MAX_LINE_SIZE))
	{
		ParseLine(szLine);
		nLineCount++;
	}

	if(popelement() == NULL)
	{
		bRet = TRUE;
	}

	clearSearchResult();

	getElementByTagName("TABLE", pRoot_node);
	if(pTableHead)
	{
		int count = 0;
		search_result *pNode = pTableHead;
		while(pNode)
		{
			count++;
			pNode = pNode->pNext;
		}
		m_nTableCount = count;
	}

	//clearSearchResult();
	getElementByTagName("DESCRIPTOR", pRoot_node);
	if(pDescriptorHead)
	{
		int count = 0;
		search_result *pNode = pDescriptorHead;
		while(pNode)
		{
			count++;
			pNode = pNode->pNext;
		}
		m_nDescriptorCount = count;
	}

	m_bFileUpdated = FALSE;

	return bRet;
}

int CDVBRule::GetTableCount(void)
{	
	if(m_bFileUpdated)
	{
		FormatVerify();
	}

	if(pTableHead)
	{
		search_result *pNode = pTableHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pTableHead = NULL;
	}

	getElementByTagName("TABLE", pRoot_node);
	if(pTableHead)
	{
		int count = 0;
		search_result *pNode = pTableHead;
		while(pNode)
		{
			count++;
			pNode = pNode->pNext;
		}
		m_nTableCount = count;
	}
	
	return m_nTableCount;
}

element_node* CDVBRule::GetTable(int nIndex)
{
	search_result *pNode = pTableHead;
	element_node* pElement = NULL;
	int n = 0;

	if(nIndex >= 0 && nIndex < m_nTableCount)
	{
		while(pNode)
		{
			if(n == nIndex)
			{
				break;
			}
			pNode = pNode->pNext;
			n++;		
		}

		if(pNode)
		{
			pElement = pNode->pNode;
		}
	}

	return pElement;
}

char* CDVBRule::GetTableName(int nIndex)
{
	char* pName = NULL;
	element_node* pElement = NULL;

	pElement = GetTable(nIndex);
	if(pElement)
	{
		findElementInChildByTagName("name", pElement);
		if(pTempHead)
		{
			pName = pTempHead->pNode->pAttribute;
		}
	}
	
	return pName;
}

int CDVBRule::GetTableIndex(BYTE table_id)
{
	int nIndex = 0;

	if(table_id == 0x41)
	{
		table_id = 0x40;
	}
	if(table_id == 0x46)
	{
		table_id = 0x42;
	}
	if(table_id >= 0x4E && table_id <= 0x6F)
	{
		table_id = 0x4E;
	}

	for(nIndex = 0; nIndex < m_nTableCount; nIndex++)
	{
		element_node* pTable = GetTable(nIndex);
		if(pTable)
		{
			element_node* pTableID = NULL;
			findElementInChildByTagName("table_id", pTable);
			if(pTempHead)
			{
				pTableID = pTempHead->pNode;
			}
			element_node *pTableIDValue = NULL;
			findElementInChildByTagName("value", pTableID);
			if(pTempHead)
			{
				pTableIDValue = pTempHead->pNode;
			}
			if(pTableIDValue)
			{
				char* szTableID = pTableIDValue->pAttribute;
				BYTE bTableID = dvb_atob(szTableID);
				if(bTableID == table_id)
				{
					break;
				}
			}
		}
	}

	if( nIndex == m_nTableCount )
	{
		nIndex = 256; // for unknown table!!!
	}

	return nIndex;
}

static element_node* g_pParsingTable = NULL;
static element_node* g_pParsingDescriptor = NULL;
static element_node* g_pParsingTablePos = NULL;
static element_node* g_pParsingDescriptorPos = NULL;


static element_node* g_pParsingRoot = NULL;
static element_node* g_pDescriptorParsingRoot = NULL;
static UINT g_nCurrentNode = 1;
static UINT g_nCurrentDescriptorNode = 0;
static element_node* g_ParsingStack[8] = {0};
static element_node** g_ParsingTop = g_ParsingStack;
static element_node** g_ParsingButtom = g_ParsingStack;

static BYTE* g_pParsingPos = NULL;
static BYTE g_BitPos = 7;
static int g_section_length = 0;
static int g_descriptor_loop_length = 0;
static int g_loop_length = 0;
static int g_descriptor_length = 0;
static int g_LoopLength_InDesc = 0;
static int g_last_element_value = 0;

static BOOL g_bInLoop = FALSE;
static BOOL g_bInDescriptor = FALSE;



static void pushParsingNode(element_node* pNode)
{
	if(g_ParsingTop < g_ParsingStack + 8)
	{
		*g_ParsingTop = pNode;
		g_ParsingTop++;
	}
}
static element_node* popParsingNode(void)
{
	element_node* pElement = NULL;
	if(g_ParsingTop > g_ParsingStack)
	{
		g_ParsingTop--;
		pElement = *g_ParsingTop;
		*g_ParsingTop = NULL;
	}

	return pElement;
}
static element_node* getParsingNode(BYTE& bPosition)
{
	element_node* pNode = NULL;

	pNode = getChildNode(g_nCurrentNode, g_pParsingRoot);

	if(pNode)
	{
		if(getElementDepth(pNode)<2)
		{
			char *pName = pNode->pName;
			if(strcmp(pName, "descriptor") == 0 && g_pParsingPos)
			{
				BYTE descriptor_tag = *g_pParsingPos;
				int descriptor_length = g_pParsingPos[1];
				
				g_bInDescriptor = TRUE;
				int nIndex = getDescriptorIndex(descriptor_tag);
				if(nIndex < getDescriptorCount())
				{//found the descriptor					
					g_pParsingDescriptor = getDescriptor(nIndex);
					g_pDescriptorParsingRoot = g_pParsingDescriptor;
					g_nCurrentDescriptorNode = 1;
					bPosition++;
				}
				else
				{//not found
					
				}				
			}
			else
			{
				g_nCurrentNode++;
				if(getChildNode(g_nCurrentNode, g_pParsingRoot) == NULL)//draw last node of the level, and next on should be upper level;
				{
					bPosition--;
				}				
			}
		}
		else
		{
			g_pParsingRoot->bProgress = g_nCurrentNode;
			pushParsingNode(g_pParsingRoot);			
			bPosition++;	//need go to lower level from next node.
			g_pParsingRoot = pNode;
			g_nCurrentNode = 0;
		}
	}
	else
	{
		g_pParsingRoot = popParsingNode();
		if(g_pParsingRoot)
		{
			if(g_bInLoop && g_section_length > 4)
			{
				g_nCurrentNode = g_pParsingRoot->bProgress;
				bPosition--;
			}
			else
			{
				g_bInLoop = FALSE;
				g_nCurrentNode = g_pParsingRoot->bProgress + 1;
				bPosition--;
			}
		}
	}
	return pNode;
}


static element_node* g_ParsingDescStack[8] = {0};
static element_node** g_ParsingDescTop = g_ParsingDescStack;
static element_node** g_ParsingDescButtom = g_ParsingDescStack;
static void pushParsingDescNode(element_node* pNode)
{
	if(g_ParsingDescTop < g_ParsingDescStack + 8)
	{
		*g_ParsingDescTop = pNode;
		g_ParsingDescTop++;
	}
}
static element_node* popParsingDescNode(void)
{
	element_node* pElement = NULL;
	if(g_ParsingDescTop > g_ParsingDescStack)
	{
		g_ParsingDescTop--;
		pElement = *g_ParsingDescTop;
		*g_ParsingDescTop = NULL;
	}

	return pElement;
}
static element_node* getParsingDescriptorNode(BYTE &bPosition)
{
	element_node* pNode = NULL;

	pNode = getChildNode(g_nCurrentDescriptorNode, g_pDescriptorParsingRoot);

	if(pNode)
	{
		if(getElementDepth(pNode)<2)
		{
			g_nCurrentDescriptorNode++;
			if(getChildNode(g_nCurrentDescriptorNode, g_pDescriptorParsingRoot) == NULL)//draw last node of the level, and next on should be upper level;
			{
				bPosition--;
			}
		}
		else
		{
			g_pDescriptorParsingRoot->bProgress = g_nCurrentDescriptorNode;
			pushParsingDescNode(g_pDescriptorParsingRoot);
			bPosition++;
			g_pDescriptorParsingRoot = pNode;
			g_nCurrentDescriptorNode = 0;
		}
	}
	else
	{
		g_pDescriptorParsingRoot = popParsingDescNode();
		
		if(g_pDescriptorParsingRoot)
		{
			if(g_LoopLength_InDesc > 0 && g_descriptor_length > 0)
			{
				g_nCurrentDescriptorNode = g_pDescriptorParsingRoot->bProgress;
			}
			else
			{
				g_nCurrentDescriptorNode = g_pDescriptorParsingRoot->bProgress + 1;
			}
			pNode = getParsingDescriptorNode(bPosition);

		}
		else
		{
			g_bInDescriptor = FALSE;
			g_nCurrentDescriptorNode = 1;				
			bPosition--;
			if(g_descriptor_loop_length <= 0)
			{
				g_nCurrentNode++;
			}
		}
	}

	return pNode;
}

static BOOL getValue(BYTE NumOfBits, DWORD& value)
{
	BOOL bRet = FALSE;
	value = 0;
	
	if(g_pParsingPos && g_BitPos < 8)
	{
		if(NumOfBits >0 &&NumOfBits <= 32)
		{
			BYTE i = 0;
			BYTE c = 0;
			while(i < NumOfBits)
			{
				c = ((*g_pParsingPos)&(0x1 << g_BitPos))>>g_BitPos;

				g_BitPos = (g_BitPos+7)%8;
				if(g_BitPos == 7)
				{
					g_pParsingPos++;
					if(g_section_length > 0)
					{
						g_section_length --;
					}
					if(g_descriptor_length > 0)
					{
						g_descriptor_length--;
					}
				}
				value = (value<<1)+c;
				i++;
			}
			bRet = TRUE;
		}
	}

	return bRet;
}

static void dvb_getText(char* dest, int nMaxSize, BYTE* pData, int len)
{
	if(dest && pData && len < nMaxSize -1 && g_BitPos == 7)
	{
		memcpy(dest, pData, len);
		dest[len] = '\0';
		g_pParsingPos += len;
		g_descriptor_length -= len;
		g_section_length -= len;
	}
}

static BOOL isInLoop(char* pName)
{
	if(pName)
	{
		int len = strlen(pName);
		if(len >= 4)
		{
			char temp[5] = {0};
			strncpy_s(temp, 5, pName, 4);
			temp[4] = '\0';
			if(strcmp(temp, "LOOP") == 0)
			{
				g_bInLoop = TRUE;
			}
		}
	}
	return g_bInLoop;
}

static BOOL isLoop(char* pName)
{
	BOOL bRet = FALSE;
	if(pName)
	{
		int len = strlen(pName);
		if(len >= 4)
		{
			char temp[5] = {0};
			strncpy_s(temp, 5, pName, 4);
			temp[4] = '\0';
			if(strcmp(temp, "LOOP") == 0)
			{
				bRet = TRUE;
			}
		}
	}
	return bRet;
}

static void preprocessingName(char* pName)
{
	if(pName)
	{
		isInLoop(pName);
	}
}



static void updateLoopName(char* pName)
{

}

static BOOL isLength(char* pName)
{
	BOOL bRet = FALSE;

	if(pName)
	{
		if(strlen(pName) > 6)
		{
			char *pSub = pName + strlen(pName) - 6;
			if(strcmp(pSub, "length") == 0)
			{
				bRet = TRUE;
			}
		}
	}

	return bRet;
}


static void ParseDescriptor(char* pLine, char* pName, char* pType, char* pValue)
{
	if(g_descriptor_loop_length == 0 && strcmp(pName, "descriptor") == 0)
	{
		g_descriptor_loop_length = g_last_element_value;
	}

	if(g_pDescriptorParsingRoot)
	{
		BYTE DefaultValue = 0;
		BYTE NumOfBits = 0;
		DWORD Value;
		BOOL bRet = FALSE;

		if(pType)
		{		
			NumOfBits = dvb_formatType(pType);
			if(pValue)
			{
				DefaultValue = dvb_atob(pValue);
			}

			if(pName)
			{
				if(strcmp(pName, "char") == 0 && g_LoopLength_InDesc >=0 )
				{
					dvb_getText(pLine, 128, g_pParsingPos, g_LoopLength_InDesc);
					g_LoopLength_InDesc = 0;
					return;
				}	
			}

			if(getValue(NumOfBits, Value))
			{
				if(pName)
				{
					if(strcmp(pName, "descriptor_length") == 0 && g_descriptor_length == 0)
					{
						g_descriptor_length = Value;
						g_descriptor_loop_length -= g_descriptor_length +2;
					}					
				}		

				g_last_element_value = Value;

				if(pLine)
				{
					if(pValue)
					{
						if(Value == DefaultValue)
						{
							sprintf_s(pLine, 128, "%s: 0x%02X",pName, Value);
						}
						else
						{
							sprintf_s(pLine, 128, "%s: 0x%02X(ERROR! the default value should be 0x%02X)",pName, Value, DefaultValue);
						}
					}
					else
					{
						sprintf_s(pLine, 128, "%s: 0x%02X",pName, Value);
					}
				}
			}
			else
			{
				if(pLine)
				{
					sprintf_s(pLine, 128, "%s:(ERROR hanppened in parsing!!!)",pName);
				}
			}
		}
		else
		{			
			//
			if(pName)
			{
				if(strcmp(pName, "descriptor") == 0)
				{
					BYTE bTag = *g_pParsingPos;
					int index = getDescriptorIndex(bTag);
					if(index < getDescriptorCount())
					{
						pName = getDescriptorName(index);
					}
				}
				if(isLoop(pName) && g_LoopLength_InDesc == 0)
				{
					g_LoopLength_InDesc = g_last_element_value;
				}

				sprintf_s(pLine, 128, "%s", pName);
			}			
		}	
	}
	else
	{
		//unknown descriptor;
		BYTE bTag = *g_pParsingPos;
		g_pParsingPos++;
		UINT nDescriptorLen = *g_pParsingPos;
		g_pParsingPos += nDescriptorLen + 1;
		g_section_length -= 2 + nDescriptorLen;
		g_descriptor_loop_length -= 2 + nDescriptorLen;
		g_descriptor_length = 0;
		g_bInDescriptor = FALSE;
		if(pLine)
		{
			sprintf_s(pLine, 128, "Descriptor(Tag=0x%02X)", bTag);
		}

		if(g_descriptor_loop_length <= 0)
		{
			g_nCurrentNode++;
		}
	}
}

static void ParseTableSection(char* pLine, char* pName, char* pType, char* pValue)
{
	BYTE DefaultValue = 0;
	BYTE NumOfBits = 0;
	DWORD Value;
	BOOL bRet = FALSE;

	if(pName)
	{
		preprocessingName(pName);
	}

	if(pType)
	{		
		NumOfBits = dvb_formatType(pType);
		if(pValue)
		{
			DefaultValue = dvb_atob(pValue);
		}

		if(getValue(NumOfBits, Value))
		{
			
			if(pName)
			{
				if(strcmp(pName, "section_length") == 0 && g_section_length == 0)
				{
					g_section_length = Value;
				}				
			}
			
			g_last_element_value = Value;

			if(pLine)
			{
				if(pValue)
				{
					if(Value == DefaultValue)
					{
						sprintf_s(pLine, 128, "%s: 0x%02X",pName, Value);
					}
					else
					{
						sprintf_s(pLine, 128, "%s: 0x%02X(ERROR! the default value should be 0x%02X)",pName, Value, DefaultValue);
					}
				}
				else
				{
					sprintf_s(pLine, 128, "%s: 0x%02X",pName, Value);
				}
			}
		}
		else
		{
			if(pLine)
			{
				sprintf_s(pLine, 128, "%s:(ERROR hanppened in parsing!!!)",pName);
			}
		}
	}
	else
	{
		if(pLine && pName)
		{
			if(isLoop(pName) && g_loop_length == 0)
			{
				g_loop_length = g_last_element_value;
			}
			if(isLoop(pName))
			{
				pName += 5;
			}

			sprintf_s(pLine, 128, "%s", pName);
		}
	}	
}

BOOL CDVBRule::ParseTable(int nIndex, BYTE* pData, char* pLine, BYTE& bPosition)
{
	BOOL bRet = FALSE;
	element_node* pTable = NULL;

	pTable = GetTable(nIndex);
	if(g_pParsingTable != pTable)//parsing a new table
	{
		g_pParsingTable = pTable;
		g_pParsingRoot = pTable;
		g_nCurrentNode = 1;

		//For parsing section
		g_pParsingPos = pData;
		g_section_length = 0;
		g_BitPos = 7;
	}

	if(pLine)
	{
		char *pType = NULL;
		char *pValue = NULL;
		char *pName = NULL;
		element_node* pParsingNode = NULL;

		if(g_bInDescriptor)
		{
			pParsingNode = getParsingDescriptorNode(bPosition);
			bRet = TRUE;
		}
		else
		{
			pParsingNode = getParsingNode(bPosition);
			if(pParsingNode == NULL && g_pParsingRoot == NULL)
			{
				g_pParsingTable = NULL;
				g_section_length = 0;
			}
			else
			{
				bRet = TRUE;
			}
		}

		if(pParsingNode)
		{
			findElementInChildByTagName("type", pParsingNode);
			pName = pParsingNode->pName;
			if(pTempHead)
			{
				pType = pTempHead->pNode->pAttribute;
			}
			findElementInChildByTagName("value", pParsingNode);
			if(pTempHead)
			{
				pValue = pTempHead->pNode->pAttribute;
			}

			if(pData == NULL)
			{
				if(pType)
				{
					sprintf_s(pLine, 128, "%s : %s", pName, pType);
				}
				else
				{
					sprintf_s(pLine, 128, "%s", pName);
				}
				pLine[strlen(pLine)] = '\0';
			}
			else
			{
				//parsing the section
				if(g_bInDescriptor)
				{
					ParseDescriptor(pLine, pName, pType, pValue);
				}
				else
				{
					ParseTableSection(pLine, pName, pType, pValue);
				}
			}			
		}
		else // no node anymore...
		{			
			pLine[0] = '\0';
		}
	}

	return bRet;
}

BOOL CDVBRule::AddTable(DWORD_PTR pTable)
{
	BOOL bRet = FALSE;

	if(pTable != NULL)
	{
		element_node* pTableNode = (element_node*)pTable;
		element_node* pLastTable = GetTable(GetTableCount()-1);
		pLastTable->pNextNode = pTableNode;
		m_nTableCount++;
		bRet = TRUE;
	}

	return bRet;
}

BOOL CDVBRule::RebuildXML(void)
{
	BOOL bRet = FALSE;

	if(pRoot_node)
	{
		m_hRulesFile->SetLength(0);
		m_hRulesFile->Seek(0, CFile::begin);
		bRet = outputXMLTree(m_hRulesFile, pRoot_node);
		m_hRulesFile->Flush();
		m_bFileUpdated = TRUE;
	}
	
	bRet = FormatVerify();

	return bRet;
}


CDVBRuleTable::CDVBRuleTable(void)
{

}

CDVBRuleTable::~CDVBRuleTable(void)
{

}

LPCTSTR CDVBRuleTable::GetName(void)
{
	return NULL;
}

static BOOL GetLine(CFile* hFile, ULONGLONG &nPos, char* szLine, int nMaxSize)
{
	BOOL bRet = FALSE;
	char ch = 0;

	if(hFile && szLine)
	{
		
		char ch_pre = 0;
		int nIndex = 0;
		int nRead = 0;
		hFile->Seek(nPos, CFile::begin);
		nRead = hFile->Read(&ch, 1);
		while(ch && nIndex < nMaxSize-1 && nRead>0)
		{			
			szLine[nIndex] = ch;
			nIndex++;
			if(ch==0x0A&&ch_pre==0x0D)
			{
				break;
			}		

			ch_pre = ch;
			nRead = hFile->Read(&ch, 1);
			bRet = TRUE;
		}
		szLine[nIndex] = '\0';
		nPos += nIndex;
	}

	return bRet;
}

static BOOL IsSkipped(const char c)
{
	BOOL bRet = FALSE;
	for(int n = 0; n < sizeof(skipped); n++)
	{
		if (c == skipped[n])
		{
			bRet = TRUE;
			break;
		}
	}
	return bRet;
}

static BOOL ParseLine(char* szLine)
{
	BOOL bRet = FALSE;

	if(szLine)
	{
		char *pc = szLine;
		
		while(*pc)
		{
			if(!IsSkipped(*pc))
			{
				readchar(*pc);
			}
			pc++;
		}
	}

	return bRet;
}

static void readchar(const char ch)
{
	switch(ch)
	{
	case '<':
		{
			if(pWrite > value && pWrite <= value + 31)
			{
				//value
				element_node* pElement = gettopelement();
				if(pElement)
				{
					*pWrite = '\0';
					int len = strlen(value)+1;
					pElement->pAttribute = new char[len];
					if(pElement->pAttribute)
					{
						strcpy_s(pElement->pAttribute, len, value);
						pElement->pAttribute[strlen(pElement->pAttribute)] = '\0';
					}
					pElement->status |= ELEMENT_ATTRIBUTE;
				}
			}
			status = ELEMENT_TAG;
			memset(element, 0, sizeof(element));
			pWrite = element;
		}
		break;
	case '>':
		{
			status = ELEMENT_VALUE;
			*pWrite = '\0';
			int len = strlen(element)+1;

			if(element[0] == '/')
			{
				element_node* pElement = popelement();
				if(strcmp(&element[1], pElement->pName)==0)
				{
					//Element ending
					pElement->status |= ELEMENT_END;
				}
				else
				{
					//error???
					pushelement(pElement);
				}
			}
			else
			{
				element_node* pElement = new element_node;
				pElement->status = 0;
				pElement->pAttribute = NULL;
				pElement->pChildNode = NULL;
				pElement->pName = NULL;
				pElement->pNextNode = NULL;
				element_node* pTop = gettopelement();
				if(pElement)
				{
					pElement->pName = new char[len];
					if(pElement->pName)
					{
						strcpy_s(pElement->pName, len, element);
						pElement->pName[strlen(pElement->pName)] = '\0';					
					}
					pElement->status |= ELEMENT_START;
					pushelement(pElement);
					if(pTop == NULL)
					{
						createroot(pElement);
					}
					else
					{
						addChild(pElement,pTop);
					}
				}
			}
			memset(value, 0, sizeof(value));
			pWrite = value;
		}
		break;
	default:
		{
			*pWrite = ch;
			pWrite++;
		}
		break;
	}
}

static void pushelement(element_node *pElement)
{
	if(stack_top < element_stack + ELEMENT_DEPTH)
	{
		*stack_top = pElement;
		stack_top++;
	}
}

static element_node* popelement(void)
{
	element_node* pElement = NULL;
	if(stack_top > element_stack)
	{
		stack_top--;
		pElement = *stack_top;
		*stack_top = NULL;
	}

	return pElement;
}

static element_node* gettopelement(void)
{
	element_node* pElement = NULL;
	if(stack_top > element_stack)
	{		
		pElement = *(stack_top-1);
	}

	return pElement;
}

static BOOL createroot(element_node* pNode)
{
	BOOL bRet = FALSE;
	if(pNode)
	{		
		pRoot_node = pNode;
		bRet = TRUE;
	}

	return bRet;
}

static BOOL addChild(element_node* pNode, element_node *pParent)
{
	BOOL bRet = FALSE;
	if(pNode && pParent)
	{		
		if(pParent->pChildNode == NULL)
		{
			pParent->pChildNode = pNode;
		}
		else
		{
			element_node* pChild = pParent->pChildNode;
			element_node* pInsert = NULL;
			while(pChild)
			{
				pInsert = pChild;
				pChild = pChild->pNextNode;
			}

			pInsert->pNextNode = pNode;
		}
		bRet = TRUE;
	}

	return bRet;
}

static BOOL freeDVBTree(element_node* pTreeRoot)
{
	BOOL bRet = FALSE;

	if(pTreeRoot)
	{
		if(pTreeRoot->pChildNode)
		{
			freeDVBTree(pTreeRoot->pChildNode);
			pTreeRoot->pChildNode = NULL;
		}
		if(pTreeRoot->pNextNode)
		{
			freeDVBTree(pTreeRoot->pNextNode);	
			pTreeRoot->pNextNode = NULL;
		}

		if(pTreeRoot->pAttribute)
		{
			delete[] pTreeRoot->pAttribute;
			pTreeRoot->pAttribute = NULL;
		}

		if(pTreeRoot->pName)
		{
			delete[] pTreeRoot->pName;
			pTreeRoot->pName = NULL;
		}

		delete pTreeRoot;		
		pTreeRoot = NULL;

		bRet = TRUE;
	}

	return bRet;
}


static void getElementByTagName(char *pName, element_node *pTree)
{
	if(pName && pTree)
	{
		if(pTree->pChildNode)
		{
			getElementByTagName(pName, pTree->pChildNode);
		}
		if(pTree->pNextNode)
		{
			getElementByTagName(pName, pTree->pNextNode);
		}
		if(pTree->pName)
		{
			if(strcmp(pName, pTree->pName) == 0)
			{
				addSearchResult(pTree);
			}
		}
	}
}

static BOOL addSearchResult(element_node* pNode)
{
	BOOL bRet = FALSE;

	if(pNode)
	{
		search_result **pResultHead = NULL;

		if(strcmp(pNode->pName, "TABLE") == 0)
		{
			pResultHead = &pTableHead;
		}
		else if(strcmp(pNode->pName, "DESCRIPTOR") == 0)
		{
			pResultHead = &pDescriptorHead;
		}
		else
		{
			pResultHead = &pTempHead;
		}
		search_result *pResult = new search_result;
		if(pResult)
		{
			pResult->pNode = pNode;
			pResult->pNext = NULL;
		}

		if(*pResultHead == NULL)
		{
			*pResultHead = pResult;
		}
		else
		{
			pResult->pNext = *pResultHead;
			*pResultHead = pResult;
		}
		bRet = TRUE;
	}

	return bRet;
}

static BOOL clearSearchResult(void)
{
	BOOL bRet = FALSE;
	if(pTableHead)
	{
		search_result *pNode = pTableHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pTableHead = NULL;
		bRet = TRUE;
	}

	if(pDescriptorHead)
	{
		search_result *pNode = pDescriptorHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pDescriptorHead = NULL;
		bRet = TRUE;
	}

	if(pTempHead)
	{
		search_result *pNode = pTempHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pTempHead = NULL;
		bRet = TRUE;
	}

	return bRet;
}

static int getDescriptorCount(void)
{
	int nDescriptorCount = 0;
	if(pDescriptorHead)
	{
		search_result* pNode = pDescriptorHead;
		while(pNode)
		{
			nDescriptorCount++;
			pNode = pNode->pNext;
		}
	}
	return nDescriptorCount;
}

static element_node* getDescriptor(int nIndex)
{
	element_node* pDescriptor = NULL;
	search_result* pNode = pDescriptorHead;
	int n = 0;
	
	while(pNode)
	{
		if(n == nIndex)
		{
			pDescriptor = pNode->pNode;
			break;
		}
		pNode = pNode->pNext;
		n++;
	}

	return pDescriptor;
}

static int getDescriptorIndex(BYTE bDescriptorTag)
{
	int n;
	for(n = 0; n < getDescriptorCount(); n++)
	{
		element_node* pDescriptor = getDescriptor(n);
		if(pDescriptor)
		{
			findElementInChildByTagName("descriptor_tag", pDescriptor);
			if(pTempHead)
			{
				element_node* pTagNode = pTempHead->pNode;
				findElementInChildByTagName("value", pTagNode);
				if(pTempHead)
				{
					char* pTagValue = pTempHead->pNode->pAttribute;
					BYTE tag = dvb_atob(pTagValue);
					if(tag == bDescriptorTag)
					{
						break;
					}
				}
			}
		}
	}

	return n;
}

static char* getDescriptorName(int nIndex)
{
	char *pName = NULL;
	element_node* pDescriptor = getDescriptor(nIndex);
	if(pDescriptor)
	{
		findElementInChildByTagName("name", pDescriptor);
		if(pTempHead)
		{
			element_node* pNameNode = pTempHead->pNode;
			if(pNameNode)
			{
				pName = pNameNode->pAttribute;
			}
		}
	}

	return pName;
}

//the result should only one!!!
static void findElementByTagName(char *pName, element_node *pTree)
{
	if(pTempHead)
	{
		search_result *pNode = pTempHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pTempHead = NULL;
	}

	getElementByTagName(pName, pTree);
}

static void findElementInChildByTagName(char *pName, element_node *pTree)
{
	if(pTempHead)
	{
		search_result *pNode = pTempHead;
		while(pNode)
		{
			search_result *pRelease = pNode;
			pNode = pNode->pNext;
			delete pRelease;
			pRelease = NULL;
		}
		pTempHead = NULL;
	}

	element_node* pNode = pTree;
	if(pNode)
	{
		pNode = pNode->pChildNode;
		while(pNode)
		{
			if(strcmp(pName, pNode->pName) == 0)
			{
				addSearchResult(pNode);
			}
			pNode = pNode->pNextNode;
		}
	}
}

static element_node* getChildNode(int nIndex, element_node* pNode)
{
	element_node* pChild = NULL;

	if(pNode)
	{
		element_node* pReturn = pNode->pChildNode;
		int n = 0;
		while(pReturn)
		{
			if (n == nIndex)
			{
				pChild = pReturn;
				break;
			}

			pReturn = pReturn->pNextNode;
			n++;
		}
	}

	return pChild;
}

static int getElementDepth(element_node* pElement)
{
	int nDepth = 0;
	if(pElement)
	{
		element_node* pNode = pElement->pChildNode;

		while(pNode)
		{
			nDepth++;
			pNode = pNode->pChildNode;
		}
	}

	return nDepth;
}

static int nDistance = 0;
static BOOL outputXMLTree(CFile* hFile, element_node* pTreeRoot)
{
	BOOL bRet = FALSE;

	if(pTreeRoot && hFile)
	{
		char* pName = pTreeRoot->pName;
		char* pAttribute = pTreeRoot->pAttribute;
		char szOutput[128] = {0};
		
		if(pAttribute)
		{
			sprintf_s(szOutput, 128, "<%s>%s", pName, pAttribute);
			szOutput[strlen(pName)+2+strlen(pAttribute)] = '\0';
		}
		else
		{
			sprintf_s(szOutput, 128, "<%s>", pName);
			szOutput[strlen(pName)+2] = '\0';
		}
		hFile->Write(szOutput, strlen(szOutput));
		if(pTreeRoot->pChildNode)
		{
			nDistance++;
			hFile->Write("\r\n", 2);
			for(int n = 0; n < nDistance; n++)
			{
				hFile->Write("\t", 1);
			}
			outputXMLTree(hFile, pTreeRoot->pChildNode);
			nDistance--;
		}		

		sprintf_s(szOutput, 128, "</%s>", pName);
		szOutput[strlen(pName)+3] = '\0';
		if(pTreeRoot->pAttribute)
		{
			hFile->Write(szOutput, strlen(szOutput));
		}
		else
		{
			hFile->Write("\r\n", 2);			
			for(int n = 0; n < nDistance; n++)
			{
				hFile->Write("\t", 1);
			}
			hFile->Write(szOutput, strlen(szOutput));
		}

		if(pTreeRoot->pNextNode)
		{
			hFile->Write("\r\n", 2);
			for(int n = 0; n < nDistance; n++)
			{
				hFile->Write("\t", 1);
			}
			outputXMLTree(hFile, pTreeRoot->pNextNode);			
		}
	}

	return bRet;
}

static BYTE dvb_atob(char* pData)
{
	BYTE bRet = 0;
	if(pData)
	{
		int n = strlen(pData);
		if(n > 2 && n < 5)
		{
			if(pData[0] == '0' && (pData[1] =='x' || pData[1] == 'X'))
			{
				int i = 2;
				while(i < n)
				{
					BYTE c = 0;

					if(pData[i] >= '0' && pData[i] <= '9')
					{
						c = pData[i] - '0';
					}
					else if(pData[i] >= 'a' && pData[i] <= 'f')
					{
						c = pData[i] - 'a'+ 0xa;
					}
					else if(pData[i] >= 'A' && pData[i] <= 'F')
					{
						c = pData[i] - 'A'+0xa;
					}
					else
					{
						bRet = 0xFF;
						break;
					}
					
					bRet = (bRet<<4)+c;
					i++;
				}
			}
			return bRet;
		}
		
		if(n < 4)
		{
			int i = 0;
			BYTE c = 0;
			while(i < n)
			{
				if(pData[i] >= '0' && pData[i] <= '9')
				{
					c = pData[i] - '0';
				}
				else
				{
					bRet = 0xFF;
					break;
				}
				bRet = bRet*10 + c;
				i++;
			}
		}
	}

	return bRet;
}

static BYTE dvb_formatType(char* pType)
{
	BYTE NumOfBits = 0;

	if(pType)
	{
		int len = strlen(pType);
		int i = 0;
		BYTE c;
		while(i < len)
		{
			if(pType[i] >= '0' && pType[i] <= '9')
			{
				c = pType[i] - '0';
			}
			else
			{
				break;
			}
			NumOfBits = NumOfBits*10 + c;
			i++;
		}
	}

	return NumOfBits;
}

